package com.derbysoft.lowcostadapter.dswitch2.service.impl;

import com.derbysoft.lowcostadapter.commons.dto.Cancel;
import com.derbysoft.lowcostadapter.commons.dto.CancelResponse;
import com.derbysoft.lowcostadapter.commons.repository.ReservationRepository;
import com.derbysoft.lowcostadapter.commons.utils.ErrorMessageUtils;
import com.derbysoft.lowcostadapter.dswitch2.service.HotelProviderService;
import com.derbysoft.lowcostadapter.dswitch2.service.helper.ResIDHelper;
import com.derbysoft.lowcostadapter.dswitch2.translator.Translator;
import com.derbysoft.lowcostadapter.webservice.LowCostWebService;
import com.derbysoft.remote.dswitch.core.*;
import com.derbysoft.remote.dswitch.generic.constants.UniqueIDType;
import com.derbysoft.remote.dswitch.hotel.dto.CancelRQ;
import com.derbysoft.remote.dswitch.hotel.dto.CancelRS;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationIDDTO;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("ds2CancelService")
public class CancelServiceImpl implements HotelProviderService<GenericRQ<CancelRQ>, GenericRS<CancelRS>> {

    private static Logger logger = LoggerFactory.getLogger(CancelServiceImpl.class);

    @Autowired
    private ReservationRepository reservationRepository;

    @Autowired
    private Translator<GenericRQ<CancelRQ>, Cancel, Void> ds2CancelRQTranslator;

    @Autowired
    private Translator<CancelResponse, GenericRS<CancelRS>, GenericRQ<CancelRQ>> ds2CancelRSTranslator;

    @Autowired
    private LowCostWebService reservationWebService;

    @Override
    public GenericRS<CancelRS> invoke(GenericRQ<CancelRQ> request) {
        try {
            Cancel cancel = ds2CancelRQTranslator.translate(request, null);
            CancelResponse cancelResponse = (CancelResponse) reservationWebService.send(cancel);
            if (StringUtils.isNotBlank(cancelResponse.getCancelResult().getReturnStatus().getException())) {
                return createFailedResponse(cancelResponse.getCancelResult().getReturnStatus().getException(), request);
            }
            GenericRS<CancelRS> response = ds2CancelRSTranslator.translate(cancelResponse, request);
            List<HotelReservationIDDTO> hotelReservationIDs = request.getPayload().getHotelReservationIDs();
            reservationRepository.cancel(
                    ResIDHelper.find(hotelReservationIDs, UniqueIDType.ERSP),
                    response.getPayload().getCancelInfo().getUniqueId().getId());
            return response;
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            String errorMessage = ErrorMessageUtils.buildErrorMessage(ex);
            return createFailedResponse(errorMessage, request);
        }
    }

    private GenericRS<CancelRS> createFailedResponse(String errorMessage, GenericRQ<CancelRQ> request) {
        GenericRS<CancelRS> genericRS = new GenericRS<CancelRS>();
        genericRS.setHeader(createHeader(request.getHeader()));
        ErrorsDTO errors = new ErrorsDTO();
        ErrorDTO errorDTO = new ErrorDTO();
        errorDTO.setCode("System");
        errorDTO.setSource("lowcostbeds provider side");
        errorDTO.setMessage(errorMessage);
        errors.getErrorList().add(errorDTO);
        genericRS.setErrors(errors);
        return genericRS;
    }

    private ResponseHeader createHeader(RequestHeader requestHeader) {
        return new ResponseHeader(requestHeader.getTaskId());
    }

    public void setReservationRepository(ReservationRepository reservationRepository) {
        this.reservationRepository = reservationRepository;
    }

    public void setDs2CancelRQTranslator(Translator<GenericRQ<CancelRQ>, Cancel, Void> ds2CancelRQTranslator) {
        this.ds2CancelRQTranslator = ds2CancelRQTranslator;
    }

    public void setDs2CancelRSTranslator(Translator<CancelResponse, GenericRS<CancelRS>, GenericRQ<CancelRQ>> ds2CancelRSTranslator) {
        this.ds2CancelRSTranslator = ds2CancelRSTranslator;
    }

    public void setReservationWebService(LowCostWebService reservationWebService) {
        this.reservationWebService = reservationWebService;
    }
}
